/*
 * vertex.cpp
 *
 *      Author: Jerome RD Soine and Christoph A Brand
 *      Institution: Schwarz goup, Institute for Theoretical Physics, Heidelberg University, Germany
 */


#include "../../../../../../include/base/cell_models/ACM/geometry/base/vertex.h"
#include <string>
#include <sstream>
#include <iostream>
#include <math.h>
#include <list>
#include <cmath>

#include "../../../../../../include/base/cell_models/ACM/geometry/base/triangle.h"
#include "../../../../../../include/base/cell_models/ACM/ActiveCableModel.h"

using namespace std;

string Vertex::toString() {
	ostringstream os;
	os << "(" << x << "," << y << "," << z << ")";
	return os.str();
}

string Vertex::toVTKString() {
	ostringstream os;
	os << x << " " << y << " " << z;
	return os.str();
}

void Vertex::removeAssociatedEdge(Edge * e){
	vector<Edge*> tmp, tmp2;
	for(unsigned int i=0; i<edgesConnectingVertex.size();i++){
		if(edgesConnectingVertex[i]!=e) tmp.push_back(edgesConnectingVertex[i]);
	}
	edgesConnectingVertex=tmp;
	for(unsigned int i=0; i<edgesOppositeToVertex.size();i++){
		if(edgesOppositeToVertex[i]!=e) tmp2.push_back(edgesOppositeToVertex[i]);
	}
	edgesOppositeToVertex=tmp2;
}



bool Vertex::operator==(Vertex const & v) const {
	bool xCoincides = (x == v.x), yCoincides = (y == v.y), zCoincides = (z == v.z);
	return (xCoincides && yCoincides && zCoincides);
}

bool Vertex::operator!=(Vertex const & v) const {
	return !(*this == v);
}

Vertex Vertex::operator+(Vertex v) {
	return Vertex(x + v.getX(), y + v.getY(), z + v.getZ());
}

Vertex Vertex::operator-(Vertex v) {
	return Vertex(x - v.getX(), y - v.getY(), z - v.getZ());
}

void Vertex::operator+=(Vertex v) {
	x += v.getX();
	y += v.getY();
	z += v.getZ();
}

void Vertex::operator-=(Vertex v) {
	x -= v.getX();
	y -= v.getY();
	z -= v.getZ();
}

double Vertex::operator*(Vertex& v) {
	return x * v.getX() +y * v.getY() +z * v.getZ();
}

Vertex Vertex::operator*(double c) {
	return Vertex(c * x, c * y, c * z);
}

Vertex Vertex::operator/(double c) {
	return Vertex(x / c, y / c, z / c);
}

Vertex Vertex::cross(Vertex v) {
	double X = v.getX();
	double Y = v.getY();
	double Z = v.getZ();
	double newX = y * Z - z * Y;
	double newY = z * X - x * Z;
	double newZ = x * Y - y * X;
	Vertex result(newX, newY, newZ);
	return result;
}



void Vertex::setCoordinates(double X, double Y, double Z) {
	x = X;
	y = Y;
	z = Z;
}

double Vertex::abs() {
	return sqrt(x*x + y*y + z*z);
}

void Vertex::moveBy(Vertex & v){
	x += v.getX();
	y += v.getY();
	z += v.getZ();
}

double Vertex::getAssociatedArea(){
	double area = 0;
//	cout << "# triangles containing vertex: " << trianglesContainingVertex.size() << endl;
	for(unsigned int i=0; i<trianglesContainingVertex.size(); i++){
		area += (*trianglesContainingVertex[i]).area();
		//cout << "Area of adjacent Triangle: " << area << endl;
	}
	return area / 3.0;
}

int Vertex::getEdgePosOfConnectingEdges(Edge * e){
	for(unsigned int i=0; i<edgesConnectingVertex.size();i++){
		if(e==edgesConnectingVertex[i]) return i;
	}
	return -1;
}

int Vertex::getEdgePosOfOppositeEdges(Edge * e){
	for(unsigned int i=0; i<edgesOppositeToVertex.size();i++){
		if(e==edgesOppositeToVertex[i]) return i;
	}
	return -1;
}

int Vertex::getTrianglePos(Triangle * t){
	for(unsigned int i=0; i<trianglesContainingVertex.size();i++){
		if(t==trianglesContainingVertex[i]) return i;
	}
	return -1;
}

bool Vertex::isEndpointOfSF(int fibernumber){
	int count = 0;
	for(unsigned int i=0; i<edgesConnectingVertex.size(); i++){
		if(edgesConnectingVertex[i]->getValueOfAttribute(ActiveCableModel::FIELD_FIBRENUMBER) == fibernumber) count++;
	}
	if(count == 1) return true;
	else return false;
}
